﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_PRODUCTS 100 // 定义商品数量最大值为 100

struct Product { // 定义 Product 结构体
	char name[50]; // 商品名称
	int quantity; // 商品数量
	float in_price; // 商品进价
	float out_price;//商品售价
};

struct Product products[MAX_PRODUCTS]; // 定义一个 Product 类型的数组，用于存储所有商品
int count = 0; // 记录已添加的商品数量

void ym_sort_menu()//排序菜单函数
{
	printf("--------------------\n");
	printf("请选择排序方式：\n");
	printf("1. 按名称降序排序\n");
	printf("2. 按数量降序排序\n");
	printf("3. 按进价降序排序\n");
	printf("4. 按售价降序排序\n");
	printf("0. 返回系统菜单\n");
	printf("--------------------\n");
}

void ym_sys_menu()//系统菜单函数
{
	printf("欢迎使用超市商品管理系统\n");
	printf("--------------------\n");
	printf("1. 添加商品\n");
	printf("2. 展示商品\n");
	printf("3. 搜索商品\n");
	printf("4. 排序商品\n");
	printf("5. 修改商品\n");
	printf("6. 删除商品\n");
	printf("0. 退出程序\n");
	printf("--------------------\n");
	printf("请输入选项：");
}

void nsj_addProduct() { // 添加商品函数
	if (count >= MAX_PRODUCTS) { // 判断是否已达到最大商品数量
		printf("无法添加更多商品。\n"); // 提示无法添加更多商品
		return; // 返回主菜单
	}

	printf("请输入商品名称："); // 提示用户输入商品名称
	scanf("%s", products[count].name); // 将用户输入的商品名称存储到数组中

	printf("请输入商品数量："); // 提示用户输入商品数量
	scanf("%d", &products[count].quantity); // 将用户输入的商品数量存储到数组中

	printf("请输入商品进价："); // 提示用户输入商品进价
	scanf("%f", &products[count].in_price); // 将用户输入的商品进价存储到数组中
	printf("请输入商品售价："); // 提示用户输入商品售价
	scanf("%f", &products[count].out_price); // 将用户输入的商品售价存储到数组中
	count++; // 增加已添加商品的数量

	printf("商品添加成功。\n"); // 提示商品添加成功
}
void saveProductsToFile() { // 保存商品信息到文件
	FILE* file = fopen("products.txt", "w"); // 打开文件（新建或覆盖原有内容）
	if (file == NULL) { // 检查文件是否成功打开
		printf("无法打开文件。\n");
		return;
	}

	for (int index = 0; index < count; index++) { // 遍历所有商品
		fprintf(file, "%s %d %.2f %.2f\n", products[index].name, products[index].quantity, products[index].in_price, products[index].out_price); // 将商品信息写入文件
	}

	fclose(file); // 关闭文件
	printf("商品信息已保存到文件。\n");
}

void loadProductsFromFile() { // 从文件加载商品信息
	FILE* file = fopen("products.txt", "r"); // 打开文件（只读模式）
	if (file == NULL) { // 如果文件不存在，则直接返回
		return;
	}

	count = 0; // 重置商品数量

	while (fscanf(file, "%s %d %f %f", products[count].name, &products[count].quantity, &products[count].in_price, &products[count].out_price) != EOF) { // 从文件读取商品信息
		count++; // 增加商品数量
	}

	fclose(file); // 关闭文件
	printf("已从文件加载商品信息。\n");
}

void nsj_displayProducts() { // 展示商品函数
	if (count == 0) { // 判断是否有商品
		printf("没有商品可展示。\n"); // 提示没有商品可展示
		return; // 返回主菜单
	}

	printf("--------------------\n"); // 打印分割线
	printf("商品列表：\n"); // 打印标题
	printf("--------------------\n"); // 打印分割线

	for (int index = 0; index < count; index++) { // 遍历所有商品
		printf("商品名称： %s\n", products[index].name); // 打印商品名称
		printf("商品数量： %d\n", products[index].quantity); // 打印商品数量
		printf("商品进价： %.2f\n", products[index].in_price); // 打印商品进价
		printf("商品售价： %.2f\n", products[index].out_price); // 打印商品售价
		printf("--------------------\n"); // 打印分割线
	}
}

void ym_searchProduct() { // 搜索商品函数
	if (count == 0) { // 判断是否有商品
		printf("没有商品可搜索。\n"); // 提示没有商品可搜索
		return; // 返回主菜单
	}

	char searchName[50]; // 定义用于存储用户输入的商品名称的数组

	printf("请输入要搜索的商品名称："); // 提示用户输入要搜索的商品名称
	scanf("%s", searchName); // 将用户输入的商品名称存储到数组中

	for (int index = 0; index < count; index++) { // 遍历所有商品
		if (strcmp(searchName, products[index].name) == 0) { // 如果找到了用户输入的商品名称
			printf("--------------------\n"); // 打印分割线
			printf("商品名称： %s\n", products[index].name); // 打印商品名称
			printf("商品数量： %d\n", products[index].quantity); // 打印商品数量
			printf("商品价格： %.2f\n", products[index].in_price); // 打印商品进价
			printf("商品价格： %.2f\n", products[index].out_price); // 打印商品售价
			printf("--------------------\n"); // 打印分割线
			return; // 返回主菜单
		}
	}

	printf("未找到该商品。\n"); // 提示未找到该商品
}

int compareNames(const void* a, const void* b) { // 比较函数：按名称降序排序
	return strcmp(((struct Product*)b)->name, ((struct Product*)a)->name); // 比较两个商品的名称并返回比较结果
}

int compareQuantities(const void* a, const void* b) { // 比较函数：按数量降序排序
	return ((struct Product*)b)->quantity - ((struct Product*)a)->quantity; // 比较两个商品的数量并返回比较结果
}

int compareInPrices(const void* a, const void* b) { // 比较函数：按进价降序排序
	return (((struct Product*)b)->in_price > ((struct Product*)a)->in_price) - (((struct Product*)b)->in_price < ((struct Product*)a)->in_price); // 比较两个商品的价格并返回比较结果
}
int compareOutPrices(const void* a, const void* b) { // 比较函数：按售价降序排序
	return (((struct Product*)b)->out_price > ((struct Product*)a)->out_price) - (((struct Product*)b)->out_price < ((struct Product*)a)->out_price); // 比较两个商品的价格并返回比较结果
}

void ym_sortProducts(int (*compareFunc)(const void*, const void*)) { // 排序函数
	if (count == 0) { // 判断是否有商品
		printf("没有商品可排序。\n"); // 提示没有商品可排序
		return; // 返回主菜单
	}

	qsort(products, count, sizeof(struct Product), compareFunc); // 使用 qsort 函数对商品进行排序

	printf("商品已按照降序排序。\n"); // 提示商品已排序
	printf("--------------------\n");
	printf("排序后的商品列表：\n");
	printf("--------------------\n");

	for (int index = 0; index < count; index++) {
		printf("商品名称： %s\n", products[index].name);
		printf("商品数量： %d\n", products[index].quantity);
		printf("商品进价： %.2f\n", products[index].in_price); // 打印商品进价
		printf("商品售价： %.2f\n", products[index].out_price); // 打印商品售价
		printf("--------------------\n");
	}
}

void gzy_editProduct() { // 修改商品函数
	if (count == 0) { // 判断是否有商品
		printf("没有商品可修改。\n"); // 提示没有商品可修改
		return; // 返回主菜单
	}

	char editName[50]; // 定义用于存储用户输入的要修改的商品名称的数组

	printf("请输入要修改的商品名称："); // 提示用户输入要修改的商品名称
	scanf("%s", editName); // 将用户输入的要修改的商品名称存储到数组中

	int index;
	for (index = 0; index < count; index++) { // 遍历所有商品
		if (strcmp(editName, products[index].name) == 0) { // 如果找到了用户输入的要修改的商品名称
			break; // 退出循环
		}
	}

	if (index == count) { // 如果没有找到用户输入的要修改的商品名称
		printf("未找到该商品。\n"); // 提示未找到该商品
		return; // 返回主菜单
	}

	printf("请输入新的商品名称："); // 提示用户输入新的商品名称
	scanf("%s", products[index].name); // 将用户输入的新的商品名称存储到数组中

	printf("请输入新的商品数量："); // 提示用户输入新的商品数量
	scanf("%d", &products[index].quantity); // 将用户输入的新的商品数量存储到数组中

	printf("请输入商品进价："); // 提示用户输入商品进价
	scanf("%f", &products[count].in_price); // 将用户输入的商品进价存储到数组中

	printf("请输入商品售价："); // 提示用户输入商品售价
	scanf("%f", &products[count].out_price); // 将用户输入的商品售价存储到数组中

	printf("商品修改成功。\n"); // 提示商品修改成功
}
void gzy_deleteProduct() { // 删除商品函数
	if (count == 0) { // 判断是否有商品
		printf("没有商品可删除。\n"); // 提示没有商品可删除
		return; // 返回主菜单
	}

	char deleteName[50]; // 定义用于存储用户输入的商品名称的数组

	printf("请输入要删除的商品名称："); // 提示用户输入要删除的商品名称
	scanf("%s", deleteName); // 将用户输入的商品名称存储到数组中

	int index;
	for (index = 0; index < count; index++) { // 遍历所有商品
		if (strcmp(deleteName, products[index].name) == 0) { // 如果找到了用户输入的商品名称
			break; // 退出循环
		}
	}

	if (index == count) { // 如果没有找到用户输入的商品名称
		printf("未找到该商品。\n"); // 提示未找到该商品
		return; // 返回主菜单
	}

	for (int i = index; i < count - 1; i++) { // 将需要删除的商品后面的所有商品向前移动
		strcpy(products[i].name, products[i + 1].name); // 将下一个商品的名称复制到当前位置
		products[i].quantity = products[i + 1].quantity; // 将下一个商品的数量复制到当前位置
		products[i].in_price = products[i + 1].in_price; // 将下一个商品的进价复制到当前位置
		products[i].out_price = products[i + 1].out_price; // 将下一个商品的售价价复制到当前位置
	}

	count--; // 减少已添加商品的数量

	printf("商品删除成功。\n"); // 提示商品删除成功
}

int main() 
{
	loadProductsFromFile();//在程序开始时从文件中加载数据
	int choice;
	
	do
	{
		ym_sys_menu();//系统菜单函数
		scanf("%d", &choice); // 获取用户输入的选项
		switch (choice) 
		{
		case 1:
			nsj_addProduct(); // 添加商品
			saveProductsToFile();// 在添加商品后保存商品信息到文件
			break;
		case 2:
			nsj_displayProducts(); // 展示商品
			break;
		case 3:
			ym_searchProduct(); // 搜索商品
			break;
		case 4:
			ym_sort_menu();//排序菜单函数
			printf("请输入选项：");
			int sortChoice;
			scanf("%d", &sortChoice); // 获取用户输入的排序选项
				switch (sortChoice) 
				{
				case 0:
					printf("返回系统菜单.\n");
					break;
				case 1:
					ym_sortProducts(compareNames); // 按名称降序排序
					break;
				case 2:
					ym_sortProducts(compareQuantities); // 按数量降序排序
					break;
				case 3:
					ym_sortProducts(compareInPrices); // 按进价降序排序
					break;
				case 4:
					ym_sortProducts(compareOutPrices);//按售价降序排序
					break;
				default:
					printf("无效的选项，请重新选择。\n");
					break;
				}
			break;
		case 5:
			gzy_editProduct(); // 修改商品
			break;
		case 6:
			gzy_deleteProduct(); // 删除商品
			break;
		case 0:
			saveProductsToFile();// 在退出程序前保存保存商品信息到文件
			printf("感谢使用，再见！\n");
			break;
		default:
			printf("无效的选项。\n");
			break;
		}
	} while (choice);

	return 0;
}